{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Horse-or-Human-Small.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "zX4Kg8DUTKWO"
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ioLbtB3uGKPX"
      },
      "source": [
        "try:\n",
        "  # %tensorflow_version only exists in Colab.\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "  pass"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RXZT2UsyIVe_"
      },
      "source": [
        "!wget --no-check-certificate \\\n",
        "    https://storage.googleapis.com/learning-datasets/horse-or-human.zip \\\n",
        "    -O /tmp/horse-or-human.zip\n",
        "\n",
        "!wget --no-check-certificate \\\n",
        "    https://storage.googleapis.com/learning-datasets/validation-horse-or-human.zip \\\n",
        "    -O /tmp/validation-horse-or-human.zip"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PLy3pthUS0D2"
      },
      "source": [
        "import os\n",
        "import zipfile\n",
        "\n",
        "local_zip = '/tmp/horse-or-human.zip'\n",
        "zip_ref = zipfile.ZipFile(local_zip, 'r')\n",
        "zip_ref.extractall('/tmp/horse-or-human')\n",
        "local_zip = '/tmp/validation-horse-or-human.zip'\n",
        "zip_ref = zipfile.ZipFile(local_zip, 'r')\n",
        "zip_ref.extractall('/tmp/validation-horse-or-human')\n",
        "zip_ref.close()\n",
        "\n",
        "# Directory with our training horse pictures\n",
        "train_horse_dir = os.path.join('/tmp/horse-or-human/horses')\n",
        "\n",
        "# Directory with our training human pictures\n",
        "train_human_dir = os.path.join('/tmp/horse-or-human/humans')\n",
        "\n",
        "# Directory with our training horse pictures\n",
        "validation_horse_dir = os.path.join('/tmp/validation-horse-or-human/horses')\n",
        "\n",
        "# Directory with our training human pictures\n",
        "validation_human_dir = os.path.join('/tmp/validation-horse-or-human/humans')\n",
        "\n",
        "train_horse_names = os.listdir('/tmp/horse-or-human/horses')\n",
        "print(train_horse_names[:10])\n",
        "\n",
        "train_human_names = os.listdir('/tmp/horse-or-human/humans')\n",
        "print(train_human_names[:10])\n",
        "\n",
        "validation_horse_hames = os.listdir('/tmp/validation-horse-or-human/horses')\n",
        "print(validation_horse_hames[:10])\n",
        "\n",
        "validation_human_names = os.listdir('/tmp/validation-horse-or-human/humans')\n",
        "print(validation_human_names[:10])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qvfZg3LQbD-5"
      },
      "source": [
        "import tensorflow as tf"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PixZ2s5QbYQ3"
      },
      "source": [
        "model = tf.keras.models.Sequential([\n",
        "    # Note the input shape is the desired size of the image 150x150 with 3 bytes color\n",
        "    # This is the first convolution\n",
        "    tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)),\n",
        "    tf.keras.layers.MaxPooling2D(2, 2),\n",
        "    # The second convolution\n",
        "    tf.keras.layers.Conv2D(32, (3,3), activation='relu'),\n",
        "    tf.keras.layers.MaxPooling2D(2,2),\n",
        "    # The third convolution\n",
        "    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),\n",
        "    tf.keras.layers.MaxPooling2D(2,2),\n",
        "    # The fourth convolution\n",
        "    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),\n",
        "    tf.keras.layers.MaxPooling2D(2,2),\n",
        "    # Flatten the results to feed into a DNN\n",
        "    tf.keras.layers.Flatten(),\n",
        "    # 512 neuron hidden layer\n",
        "    tf.keras.layers.Dense(512, activation='relu'),\n",
        "    # Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('horses') and 1 for the other ('humans')\n",
        "    tf.keras.layers.Dense(1, activation='sigmoid')\n",
        "])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8DHWhFP_uhq3"
      },
      "source": [
        "from tensorflow.keras.optimizers import RMSprop\n",
        "\n",
        "model.compile(loss='binary_crossentropy',\n",
        "              optimizer=RMSprop(lr=0.001),\n",
        "              metrics=['acc'])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ClebU9NJg99G"
      },
      "source": [
        "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
        "\n",
        "# All images will be augmented\n",
        "train_datagen = ImageDataGenerator(\n",
        "      rescale=1./255,\n",
        "      rotation_range=40,\n",
        "      width_shift_range=0.2,\n",
        "      height_shift_range=0.2,\n",
        "      shear_range=0.2,\n",
        "      zoom_range=0.2,\n",
        "      horizontal_flip=True,\n",
        "      fill_mode='nearest')\n",
        "\n",
        "# Flow training images in batches of 128 using train_datagen generator\n",
        "train_generator = train_datagen.flow_from_directory(\n",
        "        '/tmp/horse-or-human/',  # This is the source directory for training images\n",
        "        target_size=(150, 150),  # All images will be resized to 150x150\n",
        "        batch_size=128,\n",
        "        # Since we use binary_crossentropy loss, we need binary labels\n",
        "        class_mode='binary')\n",
        "\n",
        "validation_datagen = ImageDataGenerator(rescale=1/255)\n",
        "\n",
        "validation_generator = train_datagen.flow_from_directory(\n",
        "        '/tmp/validation-horse-or-human',\n",
        "        target_size=(150, 150),\n",
        "        class_mode='binary')\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Fb1_lgobv81m"
      },
      "source": [
        "history = model.fit(\n",
        "      train_generator,\n",
        "      steps_per_epoch=8,  \n",
        "      epochs=15,\n",
        "      verbose=1,\n",
        "      validation_data=validation_generator)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "o6vSHzPR2ghH"
      },
      "source": [
        "###Running the Model\n",
        "\n",
        "Let's now take a look at actually running a prediction using the model. This code will allow you to choose 1 or more files from your file system, it will then upload them, and run them through the model, giving an indication of whether the object is a horse or a human."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DoWp43WxJDNT"
      },
      "source": [
        "import numpy as np\n",
        "from google.colab import files\n",
        "from keras.preprocessing import image\n",
        "\n",
        "uploaded = files.upload()\n",
        "\n",
        "for fn in uploaded.keys():\n",
        " \n",
        "  # predicting images\n",
        "  path = '/content/' + fn\n",
        "  img = image.load_img(path, target_size=(150, 150))\n",
        "  x = image.img_to_array(img)\n",
        "  x = np.expand_dims(x, axis=0)\n",
        "\n",
        "  image_tensor = np.vstack([x])\n",
        "  classes = model.predict(image_tensor)\n",
        "  print(classes)\n",
        "  print(classes[0])\n",
        "  if classes[0]>0.5:\n",
        "    print(fn + \" is a human\")\n",
        "  else:\n",
        "    print(fn + \" is a horse\")\n",
        " "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "lVDyNR0d1JMr"
      },
      "source": [
        "# Directory with our training horse pictures\r\n",
        "train_horse_dir = os.path.join('/tmp/horse-or-human/horses')\r\n",
        "\r\n",
        "# Directory with our training human pictures\r\n",
        "train_human_dir = os.path.join('/tmp/horse-or-human/humans')\r\n",
        "\r\n",
        "# Directory with our training horse pictures\r\n",
        "validation_horse_dir = os.path.join('/tmp/validation-horse-or-human/horses')\r\n",
        "\r\n",
        "# Directory with our training human pictures\r\n",
        "validation_human_dir = os.path.join('/tmp/validation-horse-or-human/humans')\r\n",
        "\r\n",
        "train_horse_names = os.listdir('/tmp/horse-or-human/horses')\r\n",
        "print(train_horse_names[:10])\r\n",
        "\r\n",
        "train_human_names = os.listdir('/tmp/horse-or-human/humans')\r\n",
        "print(train_human_names[:10])\r\n",
        "\r\n",
        "validation_horse_hames = os.listdir('/tmp/validation-horse-or-human/horses')\r\n",
        "print(validation_horse_hames[:10])\r\n",
        "\r\n",
        "validation_human_names = os.listdir('/tmp/validation-horse-or-human/humans')\r\n",
        "print(validation_human_names[:10])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "h-SUwB0bzVvc"
      },
      "source": [
        "\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "import random\n",
        "from tensorflow.keras.preprocessing.image import img_to_array, load_img\n",
        "\n",
        "# Let's define a new Model that will take an image as input, and will output\n",
        "# intermediate representations for all layers in the previous model after\n",
        "# the first.\n",
        "successive_outputs = [layer.output for layer in model.layers[1:]]\n",
        "#visualization_model = Model(img_input, successive_outputs)\n",
        "visualization_model = tf.keras.models.Model(inputs = model.input, outputs = successive_outputs)\n",
        "# Let's prepare a random input image from the training set.\n",
        "horse_img_files = [os.path.join(train_horse_dir, f) for f in train_horse_names]\n",
        "human_img_files = [os.path.join(train_human_dir, f) for f in train_human_names]\n",
        "img_path = random.choice(horse_img_files + human_img_files)\n",
        "\n",
        "img = load_img(img_path, target_size=(150, 150))  # this is a PIL image\n",
        "x = img_to_array(img)  # Numpy array with shape (150, 150, 3)\n",
        "x = x.reshape((1,) + x.shape)  # Numpy array with shape (1, 150, 150, 3)\n",
        "\n",
        "# Rescale by 1/255\n",
        "x /= 255\n",
        "\n",
        "# Let's run our image through our network, thus obtaining all\n",
        "# intermediate representations for this image.\n",
        "successive_feature_maps = visualization_model.predict(x)\n",
        "\n",
        "# These are the names of the layers, so can have them as part of our plot\n",
        "layer_names = [layer.name for layer in model.layers]\n",
        "\n",
        "# Now let's display our representations\n",
        "for layer_name, feature_map in zip(layer_names, successive_feature_maps):\n",
        "  if len(feature_map.shape) == 4:\n",
        "    # Just do this for the conv / maxpool layers, not the fully-connected layers\n",
        "    n_features = feature_map.shape[-1]  # number of features in feature map\n",
        "    # The feature map has shape (1, size, size, n_features)\n",
        "    size = feature_map.shape[1]\n",
        "    # We will tile our images in this matrix\n",
        "    display_grid = np.zeros((size, size * n_features))\n",
        "    for i in range(n_features):\n",
        "      # Postprocess the feature to make it visually palatable\n",
        "      x = feature_map[0, :, :, i]\n",
        "      x -= x.mean()\n",
        "      x /= x.std()\n",
        "      x *= 64\n",
        "      x += 128\n",
        "      x = np.clip(x, 0, 255).astype('uint8')\n",
        "      # We'll tile each filter into this big horizontal grid\n",
        "      display_grid[:, i * size : (i + 1) * size] = x\n",
        "    # Display the grid\n",
        "    scale = 20. / n_features\n",
        "    plt.figure(figsize=(scale * n_features, scale))\n",
        "    plt.title(layer_name)\n",
        "    plt.grid(False)\n",
        "    plt.imshow(display_grid, aspect='auto', cmap='viridis')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "j4IBgYCYooGD"
      },
      "source": [
        "## Clean Up\n",
        "\n",
        "Before running the next exercise, run the following cell to terminate the kernel and free memory resources:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "651IgjLyo-Jx"
      },
      "source": [
        "import os, signal\n",
        "os.kill(os.getpid(), signal.SIGKILL)"
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}